<!DOCTYPE html>
<html lang='zh-cn'>

<head>
    <meta charset='UTF-8'>
    <meta http-equiv='X-UA-Compatible' content='IE=edge'>
    <meta name='viewport' content='width=device-width, initial-scale=1.0'>
    <title>Vue3的响应式原理</title>
    <style>
        * {
            margin: 0;
            padding: 0;
            list-style: none;
        }
    </style>
</head>

<body>
    <script>
        let person = {
            name:"张三",
            age:18
        }


        //模拟Vue2中实现响应式
        //#region 
        /* 
        const obs = new Observer(person)

        //建立person与监视者obs的联系
        let vm = person = obs

        //创建监视者
        function Observer(obj) {
            const keys = Object.keys(obj)
            keys.forEach(key=>{
                Object.defineProperty(this,key,{
                    configurable:true,
                    get(){
                        console.log(`有人读取person的${key}，getter触发`);
                        return obj[key]
                    },
                    set(value){
                        console.log(`有人修改person的${key}，setter触发`);
                        obj[key] = value
                    }
                })
            })
        } */
        //#endregion
        
        // 模拟Vue3中实现响应式（结合Proxy + Reflect实现响应式）
        //#region 
        // Proxy(target,handler)构造器用来创建Proxy对象
        // target：需要代理的目标，Proxy会对target对象进行包装，它可以是任何类型的对象
        // handler：是一个对象，内部提供了捕获Proxy对象属性操作时对应的处理函数
        // Reflect：反射对象，提供了操作对象的各种方法
        const p = new Proxy(person,{
            // 当有人读取p身上的某个属性时调用
            get(target,key){
                console.log(`有人读取了p身上的${key}`);
                return Reflect.get(target,key)
            },
            // 当有人对p进行修改/新增某个属性的时候调用
            set(target,key,value){
                console.log(`有人修改/新增了p身上的${key}，我要去更新页面了`);
                Reflect.set(target,key,value)
            },
            // 当有人删除p身上某个属性时调用
            deleteProperty(target,key){
                console.log(`有人删除了p身上的${key}，我要去更新页面了`);
                return Reflect.deleteProperty(target,key)
            }
        })
        //#endregion

        // 通过Reflect操作数据
        // 特点：当出现对象属性操作失败时，不会报错，而是返回boolean
        // let result1 = Reflect.defineProperty(person,'sex',{
        //     get(){
        //         return 1
        //     }
        // })
        // let result2 = Reflect.defineProperty(person,'sex',{
        //     get(){
        //         return 2
        //     }
        // })
        // console.log(result1);
        // console.log(result2);
        // console.log(123);
    </script>
</body>

</html>